/*
 *  TextBox.cs
 *  
 *  Represents a Windows text box control that supports prompt text.
 *  
 *  Copyright (c) 2009, Richard Bao Labs.
 *  
 *  The contents of this file are subject to the Mozilla Public License
 *  Version 1.1 (the "License"); you may not use this file except in
 *  compliance with the License. You may obtain a copy of the License at
 *  
 *  http://www.mozilla.org/MPL/
 *  
 *  Software distributed under the License is distributed on an "AS IS"
 *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 *  the License for the specific language governing rights and limitations
 *  under the License.
 *  
 *  The Original Code is RichControlLibrary.
 *  
 *  The Initial Developer of the Original Code is Richard Bao Labs.
 *  All Rights Reserved.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using RichControlLibrary.Internal;

namespace RichControlLibrary
{
    /// <summary>
    /// Represents a Windows text box control that supports prompt text.
    /// </summary>
    [DefaultEvent("ValueTextChanged")]
    public class ComboBox : 
        System.Windows.Forms.ComboBox,
        ITextControl,
        IPromptText, IAutoSelectAll, IValidation
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TextBox"/> class.
        /// </summary>
        public ComboBox()
        {
            _promptTextHelper = new PromptTextHelper(this);
            _promptTextHelper.ValueTextChanged += new EventHandler(_helper_ValueTextChanged);

            _autoSelectHelper = new AutoSelectHelper(this);
        }

        #region IPromptText related members

        private PromptTextHelper _promptTextHelper = null;

        /// <summary>
        /// Occurs when the <see cref="ValueText"/> property value changes.
        /// </summary>
        public event EventHandler ValueTextChanged;

        /// <summary>
        /// Occurs when the <see cref="PromptText"/> property value changes.
        /// </summary>
        public event EventHandler PromptTextChanged;

        /// <summary>
        /// Gets or sets the prompt text in the text box. Prompt text is used to describe what should
        /// be typed in.
        /// </summary>
        [Localizable(true)]
        [DefaultValue("Enter text here")]
        public string PromptText
        {
            get
            {
                return _promptTextHelper.PromptText;
            }
            set
            {
                _promptTextHelper.PromptText = value; 
                OnPromptTextChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Gets or sets the value text in the text box. Value text is the actual user input rather than
		/// the current display text.
        /// </summary>
        public string ValueText
        {
            get { return _promptTextHelper.ValueText; }
            set { _promptTextHelper.ValueText = value; }
        }

        /// <summary>
        /// Gets or sets the foreground color of the prompt text. It is set to 
        /// <see cref="SystemColors.GrayText"/> by default.
        /// </summary>
        [DefaultValue(typeof(Color), "GrayText")]
        public Color PromptForeColor
        {
            get { return _promptTextHelper.PromptForeColor; }
            set { _promptTextHelper.PromptForeColor = value; }
        }

        /// <summary>
        /// Gets or sets a <see cref="System.Boolean"/> value that indicates whether the prompt text is 
        /// displayed in italic.
        /// </summary>
        [Localizable(true)]
        [DefaultValue(true)]
        public bool ShowPromptInItalic
        {
            get { return _promptTextHelper.ShowPromptInItalic; }
            set { _promptTextHelper.ShowPromptInItalic = value; }
        }

        /// <summary>
        /// Gets a <see cref="System.Boolean"/> value that indicates whether the prompt text is being 
        /// displayed.
        /// </summary>
        public bool IsPromptDisplaying 
        {
            get { return _promptTextHelper.IsPromptDisplaying; }
        }

        private void _helper_ValueTextChanged(object sender, EventArgs e)
        {
            OnValueTextChanged(e);
        }

        /// <summary>
        /// Raises the <see cref="System.Windows.Forms.Control.FontChanged"/> event when the 
        /// <see cref="System.Windows.Forms.Control.Font"/> property value of the control's container 
        /// changes.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected override void OnParentFontChanged(EventArgs e)
        {
            base.OnParentFontChanged(e);
            _promptTextHelper.CheckParentAppearance();
        }

        /// <summary>
		/// Raises the <see cref="PromptTextChanged"/> event.
		/// </summary>
		/// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected virtual void OnPromptTextChanged(EventArgs e)
        {
            if (PromptTextChanged != null)
            {
                EventHandler handler = PromptTextChanged;
                handler(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ValueTextChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected virtual void OnValueTextChanged(EventArgs e)
        {
            if (ValueTextChanged != null)
            {
                EventHandler handler = ValueTextChanged;
                handler(this, e);
            }
        }

        #endregion

        #region IAutoSelectAll related members

        private AutoSelectHelper _autoSelectHelper = null;
        
        /// <summary>
        /// Gets or sets a <see cref="System.Boolean"/> value that indicates whether all text will be 
        /// selected when just focused.
        /// </summary>
        [DefaultValue(true)]
        public bool AutoSelectAllWhenFocused
        {
            get { return _autoSelectHelper.Enabled; }
            set { _autoSelectHelper.Enabled = value; }
        }

        #endregion

        #region IValidation related members

        private ValidationHelper _validationHelper = null;

        /// <summary>
        /// Gets or sets an instance of <see cref="Validator"/> to validate the user input.
        /// </summary>
        [DefaultValue(null)]
        public Validator Validator
        {
            get { return _validationHelper.Validator; }
            set { _validationHelper.Validator = value; }
        }

        /// <summary>
        /// Gets or sets a <see cref="System.Boolean"/> value that indicates whether to validate when users
        /// are typeing in the control.
        /// </summary>
        [DefaultValue(false)]
        public bool ValidateWhenTyping
        {
            get { return _validationHelper.ValidateWhenTyping; }
            set { _validationHelper.ValidateWhenTyping = value; }
        }

        /// <summary>
        /// Forces to validate the user input.
        /// </summary>
        /// <returns>A <see cref="System.Boolean"/> value that indicates whether the user input is
        /// valid.</returns>
        public bool Validate()
        {
            return _validationHelper.PerformValidate();
        }

        private void _validationHelper_InvalidInput(object sender, EventArgs e)
        {
            OnInvalidInput(EventArgs.Empty);
        }

        void _validationHelper_ValidInput(object sender, EventArgs e)
        {
            OnValidInput(EventArgs.Empty);
        }

        /// <summary>
        /// Occurs when the input is invalid.
        /// </summary>
        public event EventHandler InvalidInput;

        /// <summary>
        /// Occurs when the input is valid.
        /// </summary>
        public event EventHandler ValidInput;

        /// <summary>
        /// Raises the <see cref="InvalidInput"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected virtual void OnInvalidInput(EventArgs e)
        {
            if (InvalidInput != null)
            {
                EventHandler handler = InvalidInput;
                handler(this, e);
            }
        }

        /// <summary>
        /// Raises the <see cref="ValidInput"/> event.
        /// </summary>
        /// <param name="e">An <see cref="System.EventArgs"/> that contains the event data.</param>
        protected virtual void OnValidInput(EventArgs e)
        {
            if (ValidInput != null)
            {
                EventHandler handler = ValidInput;
                handler(this, e);
            }
        }

        #endregion
    }
}
